package client;

import dto.Request;
import dto.Response;

import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.Socket;
import java.util.List;
import java.util.Map;

/**
 * 数据库客户端
 * 提供简单的API接口
 */
@Slf4j
public class DatabaseClient implements AutoCloseable {
    
    private final String host;
    private final int port;
    private Socket socket;
    private ObjectInputStream inputStream;
    private ObjectOutputStream outputStream;
    private boolean connected;
    
    public DatabaseClient(String host, int port) {
        this.host = host;
        this.port = port;
        this.connected = false;
    }
    
    /**
     * 连接到服务器
     */
    public boolean connect() {
        try {
            socket = new Socket(host, port);
            outputStream = new ObjectOutputStream(socket.getOutputStream());
            inputStream = new ObjectInputStream(socket.getInputStream());
            connected = true;
            log.info("成功连接到服务器: {}:{}", host, port);
            return true;
        } catch (IOException e) {
            log.error("连接服务器失败: {}:{}, error={}", host, port, e.getMessage());
            return false;
        }
    }
    
    /**
     * 断开连接
     */
    public void disconnect() {
        connected = false;
        try {
            if (inputStream != null) inputStream.close();
            if (outputStream != null) outputStream.close();
            if (socket != null) socket.close();
            log.info("已断开与服务器的连接");
        } catch (IOException e) {
            log.error("断开连接失败: error={}", e.getMessage());
        }
    }
    
    /**
     * 发送同步请求并等待响应
     */
    public Response sendRequest(Request request) {
        if (!connected) {
            log.error("客户端未连接");
            return Response.error("客户端未连接");
        }

        try {
            // 同步发送和接收
            synchronized (this) {
                outputStream.writeObject(request);
                outputStream.flush();
                return (Response) inputStream.readObject();
            }
        } catch (IOException | ClassNotFoundException e) {
            log.error("发送同步请求失败: error={}", e.getMessage());
            disconnect(); // 连接出现问题，断开
            return Response.error("网络通信失败: " + e.getMessage());
        }
    }

    /**
     * 异步发送请求，不等待响应
     */
    public void sendRequestAsync(Request request) {
        if (!connected) {
            log.error("客户端未连接");
            return;
        }

        try {
            // 异步发送，不需要同步块
            outputStream.writeObject(request);
            outputStream.flush();
        } catch (IOException e) {
            log.error("发送异步请求失败: error={}", e.getMessage());
            disconnect(); // 连接出现问题，断开
        }
    }
    
    // 基本CRUD操作API
    
    /**
     * 存储键值对
     */
    public <T> boolean put(String key, T value) {
        Request request = new Request(Request.RequestType.PUT);
        request.setKey(key);
        request.setValue(value);
        request.setValueType(value.getClass().getName());
        
        Response response = sendRequest(request);
        return response.getStatus() == Response.ResponseStatus.SUCCESS;
    }
    
    /**
     * 获取值
     */
    @SuppressWarnings("unchecked")
    public <T> T get(String key, Class<T> clazz) {
        Request request = new Request(Request.RequestType.GET);
        request.setKey(key);
        request.setValueType(clazz.getName());
        
        Response response = sendRequest(request);
        if (response.getStatus() == Response.ResponseStatus.SUCCESS) {
            return (T) response.getData();
        }
        return null;
    }
    
    /**
     * 更新值
     */
    public <T> boolean update(String key, T value) {
        Request request = new Request(Request.RequestType.UPDATE);
        request.setKey(key);
        request.setValue(value);
        request.setValueType(value.getClass().getName());
        
        Response response = sendRequest(request);
        return response.getStatus() == Response.ResponseStatus.SUCCESS;
    }
    
    /**
     * 删除键值对
     */
    public boolean delete(String key) {
        Request request = new Request(Request.RequestType.DELETE);
        request.setKey(key);
        
        Response response = sendRequest(request);
        return response.getStatus() == Response.ResponseStatus.SUCCESS;
    }
    
    /**
     * 检查键是否存在
     */
    public boolean containsKey(String key) {
        Request request = new Request(Request.RequestType.CONTAINS_KEY);
        request.setKey(key);
        
        Response response = sendRequest(request);
        if (response.getStatus() == Response.ResponseStatus.SUCCESS) {
            return (Boolean) response.getData();
        }
        return false;
    }
    
    /**
     * 获取所有键
     */
    @SuppressWarnings("unchecked")
    public List<String> getAllKeys() {
        Request request = new Request(Request.RequestType.GET_ALL_KEYS);
        
        Response response = sendRequest(request);
        if (response.getStatus() == Response.ResponseStatus.SUCCESS) {
            return (List<String>) response.getData();
        }
        return null;
    }
    
    /**
     * 获取所有键值对
     */
    @SuppressWarnings("unchecked")
    public <T> List<Map<String, T>> getAllKeyValues(Class<T> clazz) {
        Request request = new Request(Request.RequestType.GET_ALL_KEY_VALUES);
        request.setValueType(clazz.getName());
        
        Response response = sendRequest(request);
        if (response.getStatus() == Response.ResponseStatus.SUCCESS) {
            return (List<Map<String, T>>) response.getData();
        }
        return null;
    }
    
    // 批量操作API
    
    /**
     * 批量插入
     */
    public <T> boolean batchPut(Map<String, T> keyValueMap) {
        Request request = new Request(Request.RequestType.BATCH_PUT);
        request.setBatchData((Map<String, Object>) keyValueMap);
        
        Response response = sendRequest(request);
        return response.getStatus() == Response.ResponseStatus.SUCCESS;
    }
    
    /**
     * 批量更新
     */
    public <T> boolean batchUpdate(Map<String, T> keyValueMap) {
        Request request = new Request(Request.RequestType.BATCH_UPDATE);
        request.setBatchData((Map<String, Object>) keyValueMap);
        
        Response response = sendRequest(request);
        return response.getStatus() == Response.ResponseStatus.SUCCESS;
    }
    
    /**
     * 批量删除
     */
    public boolean batchDelete(List<String> keys) {
        Request request = new Request(Request.RequestType.BATCH_DELETE);
        request.setBatchKeys(keys);
        
        Response response = sendRequest(request);
        return response.getStatus() == Response.ResponseStatus.SUCCESS;
    }
    
    // 集合操作API
    
    /**
     * 创建集合
     */
    public boolean createCollection(String name, String description) {
        Request request = new Request(Request.RequestType.CREATE_COLLECTION);
        request.setCollectionName(name);
        request.setCollectionDescription(description);
        
        Response response = sendRequest(request);
        return response.getStatus() == Response.ResponseStatus.SUCCESS;
    }
    
    /**
     * 删除集合
     */
    public boolean deleteCollection(String name) {
        Request request = new Request(Request.RequestType.DELETE_COLLECTION);
        request.setCollectionName(name);
        
        Response response = sendRequest(request);
        return response.getStatus() == Response.ResponseStatus.SUCCESS;
    }
    
    /**
     * 获取集合
     */
    public Object getCollection(String name) {
        Request request = new Request(Request.RequestType.GET_COLLECTION);
        request.setCollectionName(name);
        
        Response response = sendRequest(request);
        if (response.getStatus() == Response.ResponseStatus.SUCCESS) {
            return response.getData();
        }
        return null;
    }
    
    /**
     * 获取所有集合
     */
    @SuppressWarnings("unchecked")
    public List<Object> getAllCollections() {
        Request request = new Request(Request.RequestType.GET_ALL_COLLECTIONS);
        
        Response response = sendRequest(request);
        if (response.getStatus() == Response.ResponseStatus.SUCCESS) {
            return (List<Object>) response.getData();
        }
        return null;
    }
    
    /**
     * 在集合中存储数据
     */
    public <T> boolean putInCollection(String collectionName, String key, T value) {
        Request request = new Request(Request.RequestType.PUT_IN_COLLECTION);
        request.setCollectionName(collectionName);
        request.setKey(key);
        request.setValue(value);
        request.setValueType(value.getClass().getName());
        
        Response response = sendRequest(request);
        return response.getStatus() == Response.ResponseStatus.SUCCESS;
    }
    
    /**
     * 从集合中获取数据
     */
    @SuppressWarnings("unchecked")
    public <T> T getFromCollection(String collectionName, String key, Class<T> clazz) {
        Request request = new Request(Request.RequestType.GET_FROM_COLLECTION);
        request.setCollectionName(collectionName);
        request.setKey(key);
        request.setValueType(clazz.getName());
        
        Response response = sendRequest(request);
        if (response.getStatus() == Response.ResponseStatus.SUCCESS) {
            return (T) response.getData();
        }
        return null;
    }
    
    /**
     * 从集合中删除数据
     */
    public boolean deleteFromCollection(String collectionName, String key) {
        Request request = new Request(Request.RequestType.DELETE_FROM_COLLECTION);
        request.setCollectionName(collectionName);
        request.setKey(key);
        
        Response response = sendRequest(request);
        return response.getStatus() == Response.ResponseStatus.SUCCESS;
    }
    
    /**
     * 获取集合中的所有数据
     */
    @SuppressWarnings("unchecked")
    public <T> List<Object> getAllFromCollection(String collectionName, Class<T> clazz) {
        Request request = new Request(Request.RequestType.GET_ALL_FROM_COLLECTION);
        request.setCollectionName(collectionName);
        request.setValueType(clazz.getName());
        
        Response response = sendRequest(request);
        if (response.getStatus() == Response.ResponseStatus.SUCCESS) {
            return (List<Object>) response.getData();
        }
        return null;
    }
    
    // 系统操作API
    
    /**
     * 清空数据库
     */
    public boolean clear() {
        Request request = new Request(Request.RequestType.CLEAR);
        
        Response response = sendRequest(request);
        return response.getStatus() == Response.ResponseStatus.SUCCESS;
    }
    
    /**
     * 获取统计信息
     */
    @SuppressWarnings("unchecked")
    public Map<String, Object> getStatistics() {
        Request request = new Request(Request.RequestType.GET_STATISTICS);
        
        Response response = sendRequest(request);
        if (response.getStatus() == Response.ResponseStatus.SUCCESS) {
            return (Map<String, Object>) response.getData();
        }
        return null;
    }
    
    /**
     * 测试连接
     */
    public boolean ping() {
        Request request = new Request(Request.RequestType.PING);
        
        Response response = sendRequest(request);
        return response.getStatus() == Response.ResponseStatus.SUCCESS;
    }
    
    /**
     * 检查是否已连接
     */
    public boolean isConnected() {
        return connected && socket != null && !socket.isClosed();
    }
    
    @Override
    public void close() {
        disconnect();
    }
} 